import re

from django import http
from django.conf import settings
from django.contrib.auth import login
from django.db import DatabaseError
from django.http import response
from django_redis import get_redis_connection
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from QQLoginTool.QQtool import OAuthQQ

from apps.goods.utils import merge_carts
from utils.secret import serializer
from apps.users.models import User
from utils.response_code import RETCODE
from .models import OAuthQQUser


def is_bind_open_id(request, open_id):
    try:  # 操作数据库必须考虑失败
        qq_user = OAuthQQUser.objects.get(open_id=open_id)

    except OAuthQQUser.DoesNotExist as e:
        settings.LOGGER.info('openid未绑定用户',e)
        # 2.未绑定
        open_id = serializer.dumps(open_id).decode()
        context = {'openid':open_id}
        # 重定向到绑定页面 render(request,'cccc.html',{''})
        return render(request, 'oauth_callback.html', context)
    # 绑定了
    else:
        user = qq_user.user
        # 1.1保持登录状态-> login(request,user)
        login(request, user)
        # 1.2重定向到首页-->redirect(reverse())
        response = redirect(reverse('contents:index'))
        # 1.3设置cookie set_cookie()
        response.set_cookie(key='username', value=user.username, max_age=14*3600*24)
        # 合并cookie中的购物车数据
        response = merge_carts(user, request, response)
        return response


class QQAuthURLView(View):
    """提供QQ登录页面网址
    https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxx&redirect_uri=xxx&state=xxx
    """
    def get(self, request):
        next = request.GET.get('next')
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        login_url = oauth.get_qq_url()
        return response.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


# 回调地址视图
class OauthCallbackView(View):
    # http://www.meiduo.site:8000/oauth_callback/?code=B7CDE7F171250B3C7593596B5A968410&state=%2F
    def get(self, request):
        # 取code - -request.GET.get('code')
        code = request.GET.get('code')
        next = request.GET.get('state')

        # code - --->qq服务器 - --->token
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        token = oauth.get_access_token(code)

        # token - --->qq服务器 - -->openid(唯一id)
        # get_open_id(token)
        open_id = oauth.get_open_id(token)

        # 4.是否绑定openid
        cur_response = is_bind_open_id(request, open_id)

        return cur_response


    def post(self, request):
        # 解析参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        image_code = request.POST.get('image_code')
        sms_code = request.POST.get('sms_code')
        openid = serializer.loads(request.POST.get('openid'))

        # 校验openid
        if not openid:
            content = {'openid_errmsg': '无效的openid'}
            return render(request, 'oauth_callback.html', content)

        # 校验参数
        if not all([mobile, password, image_code, sms_code]):
            return http.HttpResponseForbidden('非法访问,参数缺失.')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('非法访问,号码格式错误.')
        if not re.match(r'^[a-zA-Z0-9\-_]{8,20}$', password):
            return http.HttpResponseForbidden('非法访问,密码错误.')
        # 校验短信验证码
        sms_code_conn = get_redis_connection('sms_code')
        redis_sms_code = sms_code_conn.get(f"sms_{mobile}")
        if not redis_sms_code:
            return render(request, template_name='oauth_callback.html', context={'sms_code_errmsg': '短信验证码已过期'})
        if redis_sms_code.decode() != sms_code:
            return render(request, template_name='oauth_callback.html', context={'sms_code_errmsg': '短信验证码输入错误'})

        # 判断手机号用户是否存在
        try:
            user = User.objects.get(mobile=mobile)

        except User.DoesNotExist:
            # 未get到报错
            # 用户不存在,新建一个
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 手机用户存在
            # 校验密码
            if not user.check_password(password):
                content = {'account_errmsg': '用户名或密码错误'}
                return render(request, 'oauth_callback.html', content)

        # 绑定openid和user
        try:
            # 新建oauth表数据
            qq_user = OAuthQQUser.objects.create(open_id=openid, user=user)
        except DatabaseError as e:
            settings.LOGGER.error(e)
            # 未知错误
            content = {'qq_login_errmsg': 'qq登陆失败'}
            return render(request, 'oauth_callback.html', content)
        else:
            login(request, qq_user.user)
            response = redirect(reverse('contents:index'))
            response.set_cookie(key='username', value=user.username, max_age=14*3600*24)
            # 合并cookie中的购物车数据
            response = merge_carts(user, request, response)
            return response
